<?php
/**
 * 处理微信扫码支付
 * Author: lyun
 * Date: 2018/4/20
 * Created by Panxsoft.
 */


namespace App\Services\Omnipay;

use App\Exceptions\ApiErrCode;
use App\Exceptions\ApiException;
use App\Http\Controllers\Api\V1\App\Order\PayNotifyController;
use App\Models\Currency;
use App\Models\Extension\Extension;
use App\Models\Order\Order;
use App\Models\Order\OrderTotal;
use App\Models\Setting;
use App\Services\Orders\PayNotifyService;
use App\Services\Utils\TimeHelper;
use Omnipay\Omnipay;
use Omnipay\WechatPay\AppGateway;
use Omnipay\WechatPay\Message\CreateOrderResponse;

class WechatPay
{
    /**
     *  微信扫码支付的 配置
     *
     * @return AppGateway
     */
    public static function getWechatGateWay()
    {
        /** @var AppGateway $gateway */
        $gateway = Omnipay::create('WechatPay_App');

        $config = Setting::findConfigByCode(Setting::CODE_PAYMENT_WECHAT);

        /** 配置文件 */
        $gateway->setAppId($config['payment_wechat_pay_app_id']);
        $gateway->setMchId($config['payment_wechat_pay_mch_id']);
        $gateway->setApiKey($config['payment_wechat_pay_api_secret']);

        return $gateway;
    }

    /**
     * 微信扫码支付 生成订单，返回二维码
     *
     * @param Order $order
     *
     * @return mixed
     * @throws \Exception
     */
    public static function getConfig(Order $order): array
    {
        $gateway = self::getWechatGateWay();
        $product_name = $order->orderProducts->first()->name ?? '';

        /** 创建订单 */
        $order = [
            'trade_type'       => 'APP',
            'body'             => $product_name,
            'detail'           => $order->payment_fullname,
            'out_trade_no'     => $order->trade_no,
            'total_fee'        => self::getWechatPayTotalFee($order),
            'notify_url'       => route(PayNotifyController::ROUTE_PAY_NOTIFY_GATEWAY_NAME, [Extension::CODE_PAYMENT_WECHAT]),
            'spbill_create_ip' => $order->ip,
            'fee_type'         => $order->currency_code
        ];

        $result = $gateway->purchase($order);

        $response = $result->send();
        self::checkConfigResponse($response);

        return $response->getAppOrderData();
    }

    /**
     *  微信支付成功的异步回调通知
     *
     * @return bool
     * @throws \Exception
     */
    public static function wechatNotify()
    {
        logger(request()->all());
        $gateway = self::getWechatGateWay();

        $response = $gateway->completePurchase([
            'request_params' => file_get_contents('php://input')
        ])->send();

        try {

            if ($response->isPaid()) { //pay success
                $data['response'] = $response->getRequestData();
                logger($data);
                $data['notify'] = WechatPay::assembleXml();

                $out_trade_no = $data['response']['out_trade_no']; // 订单号

                /** @var Order $order */
                $order = Order::findOrderUnpaidByTradeNo($out_trade_no);

                if (!$order) return false; // 没找到/已完成支付

                (new PayNotifyService)->savePaidStatus($order);

                return $data['notify'];

            } else {

                return false;
            }

        } catch (\Exception $e) {
            logger($e->getMessage());

            return false;
        }
    }

    /**
     *  成功返回 xml消息给微信
     *
     * @return string
     */
    public static function assembleXml()
    {
        $xml = "<xml>";
        $xml .= "<return_code><![CDATA[SUCCESS]]></return_code>";
        $xml .= "<return_msg><![CDATA[OK]]></return_msg>";
        $xml .= "</xml>";

        return $xml;
    }

    /**
     * @param Order $order
     * @return float|int
     */
    private static function getWechatPayTotalFee(Order $order)
    {
        $currency_code = $order->currency_code;
        $currency = Currency::getCurrencyByCode($currency_code);

//        $order_total_value = Currency::getProductTotalPriceByCurrency($order->currency_code, $order->orderTotalByTotal->value);
        $order_total_value = round($order->total * $order->currency_value, $currency->decimal_place);

        return $order_total_value * 100;
    }

    /**
     * @param $response
     *
     * @throws ApiException
     * @throws \App\Exceptions\ApiSilentException
     */
    private static function checkConfigResponse(CreateOrderResponse $response): void
    {
        if (!$response->isSuccessful()) {
            $error = $response->getData();
            logger($error);
            throw new ApiException(ApiErrCode::OPERATE_FAILED,
                $error['result_code'] . ': ' . $error['err_code_des']);
        }
    }

    /**
     *  支付成功 ，微信回调，返回的数据格式
     *
     * 'appid' => 'wx54b27058c10d2a4a',
     * 'bank_type' => 'CFT',
     * 'cash_fee' => '10',
     * 'fee_type' => 'CNY',
     * 'is_subscribe' => 'Y',
     * 'mch_id' => '1393981202',
     * 'nonce_str' => '49d5ec916b48c34d51161512d3790e62',
     * 'openid' => 'oEquaxFPI6hLAAR-56Rdf8IvhZok',
     * 'out_trade_no' => '201804201346349788',
     * 'result_code' => 'SUCCESS',
     * 'return_code' => 'SUCCESS',
     * 'sign' => '07FDD770B8375A90A1F9E05710678C83',
     * 'time_end' => '20180420134658',
     * 'total_fee' => '10',
     * 'trade_type' => 'NATIVE',
     * 'transaction_id' => '4200000055201804202404835704',
     *
     */
}
